﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Camc.Quality.TrepanningManager.PublicToSql
{
  public static  class LinqToSql
    {
        //private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
        //private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");
        //private static readonly FieldInfo QueryModelGeneratorField = typeof(QueryCompiler).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryModelGenerator");
        //private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
        //private static readonly PropertyInfo DatabaseDependenciesField = typeof(DbLoggerCategory.Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies");
        //public static string ToSql<TEntity>(this IQueryable<TEntity> query)
        //{
        //    try
        //    {
        //        var queryCompiler = (QueryCompiler)QueryCompilerField.GetValue(query.Provider);
        //        var queryModelGenerator = (QueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler);
        //        var queryModel = queryModelGenerator.ParseQuery(query.Expression);
        //        var database = DataBaseField.GetValue(queryCompiler);
        //        var databaseDependencies = (DatabaseDependencies)DatabaseDependenciesField.GetValue(database);
        //        var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false);
        //        var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
        //        modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
        //        var sql = modelVisitor.Queries.First().ToString();
        //        return sql;
        //    }
        //    catch (Exception ex)
        //    {

        //        throw;
        //    }

        //}
        //public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
        //{
        //     var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
        //    var relationalCommandCache = enumerator.Private("_relationalCommandCache");
        //    var selectExpression = relationalCommandCache.Private<Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression>("_selectExpression");
        //    var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");

        //    var sqlGenerator = factory.Create();
        //    var command = sqlGenerator.GetCommand(selectExpression);

        //    string sql = command.CommandText;
        //    return sql;
        //}

        //private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
        //private static T Private<T>(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);

        //public static string ToSql<TEntity>(this IQueryable<TEntity> query)
        //{
        //    var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
        //    var enumeratorType = enumerator.GetType();
        //    var selectFieldInfo = enumeratorType.GetField("_selectExpression", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($"cannot find field _selectExpression on type {enumeratorType.Name}");
        //    var sqlGeneratorFieldInfo = enumeratorType.GetField("_querySqlGeneratorFactory", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException($"cannot find field _querySqlGeneratorFactory on type {enumeratorType.Name}");
        //    var selectExpression = selectFieldInfo.GetValue(enumerator) as Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression ?? throw new InvalidOperationException($"could not get SelectExpression");
        //    var factory = sqlGeneratorFieldInfo.GetValue(enumerator) as Microsoft.EntityFrameworkCore.Query.Sql.IQuerySqlGeneratorFactory ?? throw new InvalidOperationException($"could not get IQuerySqlGeneratorFactory");
        //    //var sqlGenerator = factory.Create();
        //    //var command = sqlGenerator.GetCommand(selectExpression);
        //    //var sql = command.CommandText;
        //    return "";
        //}
    }
}
